Skip to main content
Version: 1.0.0

Creating histograms in Muze

Histogram is a graphical display of data using bars of different heights.It is similar to a Bar Chart but a histogram groups numbers into ranges .The height of each bar shows how many fall into each range which help us to decide what ranges to use.

Lets prepare our data

The data is as:

[
{
"delay": 20,
"distance": 570,
"time": 6.833333333333333
},
{
"delay": 7,
"distance": 588,
"time": 6.833333333333333
},
{
"delay": 16,
"distance": 590,
"time": 6.883333333333333
},
{
"delay": -19,
"distance": 1797,
"time": 6.916666666666667
}
]

We will create a histogram illustrating the number of flights vs their delay.

Let's create a Datamodel instance from the raw data and some bins depicting the delay intervals.

const { muze } = viz;

const data = [
{
delay: 20,
distance: 570,
time: 6.833333333333333,
},
{
delay: 7,
distance: 588,
time: 6.833333333333333,
},
{
delay: 16,
distance: 590,
time: 6.883333333333333,
},
{
delay: -19,
distance: 1797,
time: 6.916666666666667,
},
{
delay: -28,
distance: 1864,
time: 6.916666666666667,
},
{
delay: -10,
distance: 1481,
time: 7,
},
{
delay: -10,
distance: 361,
time: 7,
},
{
delay: -28,
distance: 1235,
time: 7,
},
{
delay: -3,
distance: 256,
time: 7,
},
{
delay: -3,
distance: 588,
time: 7,
},
{
delay: -4,
distance: 423,
time: 7,
},
{
delay: -4,
distance: 612,
time: 7,
},
{
delay: -5,
distance: 1090,
time: 7,
},
{
delay: -5,
distance: 296,
time: 7,
},
{
delay: 25,
distance: 369,
time: 2,
},
{
delay: 22,
distance: 110,
time: 6,
},
{
delay: 29,
distance: 345,
time: 7,
},
{
delay: 33,
distance: 407,
time: 7,
},
{
delay: -6,
distance: 325,
time: 7,
},
{
delay: -7,
distance: 236,
time: 7,
},
{
delay: 0,
distance: 223,
time: 7,
},
{
delay: 0,
distance: 303,
time: 7,
},
];

const schema = [
{
name: "delay",
type: "measure",
},
{
name: "distance",
type: "measure",
},
{
name: "time",
type: "measure",
},
];

const formattedData = await DataModel.loadData(data, schema);
let rootData = new DataModel(formattedData);

// Bins
const bins = new Array(200)
.fill()
.map((d, i) => i - 60)
.map((d, i) => [d * 10, (d + 1) * 10]);

Then lets create a new variable in our datamodel instance for the bins:

const binnedDM = rootData.calculateVariable(
{
name: 'delay_range',
type: 'dimension'
},
['delay'],
(no) => {
const bin = bins.find(range => no >= range[0] && no <= range[1]);
return bin ? bin.join(' - ') : undefined;
};
);

Add a counter for each flight occurrence in each bin:

const dm = binnedDM.calculateVariable(
{
name: "#Flights",
type: "measure",
},
["delay"],
() => 1,
);

Let's prepare our canvas:

muze
.canvas()
.rows(["#Flights"])
.columns(["Delay Range"])
.config({
axes: {
x: {
padding: 0,
name: "Delay",
tickFormat: (val) => val.rawValue.split(" - ")[0],
},
y: {
show: false,
numberOfTicks: 5,
},
},
border: {
// Hide the layout borders for better visibility
showValueBorders: {
left: false,
bottom: false,
},
},
sort: {
"Delay Range": (a, b) => {
const [a1, a2] = a
.split(" - ")
.filter((d) => d)
.map(Number);
const [b1, b2] = b
.split(" - ")
.filter((d) => d)
.map(Number);
return a1 - b1;
},
},
})
.layers([
{
mark: "bar",
transition: {
disabled: true,
},
encoding: {
strokeWidth: {
value: "1px",
},
},
interaction: {
highlight: {
style: {
"stroke-width": "2px",
},
},
},
className: "histogram-bar",
},
])
.title("Airline arrival delay")
.data(dm)
.width(650)
.height(500)
.mount("#chart");